package com.yz.zookeeperconfigsource.config;

import com.alibaba.druid.pool.DruidDataSource;
import com.alibaba.druid.spring.boot.autoconfigure.DruidDataSourceBuilder;
import com.yz.zookeeperconfigsource.config.properties.DruidProperties;
import org.apache.zookeeper.KeeperException;
import org.apache.zookeeper.WatchedEvent;
import org.apache.zookeeper.Watcher;
import org.apache.zookeeper.ZooKeeper;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;

import java.io.IOException;
import java.util.HashMap;

@Configuration
public class DuridConfig implements ApplicationContextAware {

    private final static String  ZOOKEEPER_HOST="azyjz.ltd:2181";
    private final static String  PATH="/config/url";
    private static ApplicationContext applicationContext;

    private ZooKeeper zooKeeper() throws IOException {
        ZooKeeper zooKeeper = new ZooKeeper(ZOOKEEPER_HOST, 5000, new Watcher() {
            @Override
            public void process(WatchedEvent event) {
                // 捕获事件状态
                if (event.getType() == Event.EventType.None) {
                    if (event.getState() == Event.KeeperState.SyncConnected) {
                        System.out.println("连接成功");
                    } else if (event.getState() == Event.KeeperState.Disconnected) {
                        System.out.println("连接断开!");
                    }else if (event.getState() == Event.KeeperState.Expired){
                        System.out.println("连接超时!");
                        // 超时后服务器端已经将连接释放，需要重新连接服务器端

                        try {
                            addWatcher();
                        } catch (IOException e) {
                            e.printStackTrace();
                        } catch (KeeperException e) {
                            e.printStackTrace();
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                }
            }
        });
        return zooKeeper;
    }

    private ZooKeeper addWatcher() throws IOException, KeeperException, InterruptedException {
        ZooKeeper zooKeeper = zooKeeper();
        zooKeeper.exists("/config/url", new Watcher() {
            public void process(WatchedEvent event) {
                if(event.getType()== Watcher.Event.EventType.NodeDataChanged){

                    DruidDataSource druidDataSource = druidDataSource();
                    DynamicDataSource bean = applicationContext.getBean(DynamicDataSource.class);
                    bean.setDataSource(druidDataSource);
                    System.out.println("==");
                    try {
                        zooKeeper.close();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }


                }
            }
        });
        return zooKeeper;
    }

    public DruidDataSource druidDataSource()  {
        DruidDataSource druidDataSource = DruidDataSourceBuilder.create().build();
        try {
            ZooKeeper zooKeeper = addWatcher();
            DruidProperties druidProperties = applicationContext.getBean(DruidProperties.class);
            druidDataSource = druidProperties.dataSource(druidDataSource);
            String host = new String(zooKeeper.getData("/config/url",true, null));
            String username = new String(zooKeeper.getData("/config/username",true, null));
            String password = new String(zooKeeper.getData("/config/password",true, null));
            druidDataSource = new DruidDataSource();
            druidDataSource.setUrl(host);
            druidDataSource.setUsername(username);
            druidDataSource.setPassword(password);
        }catch (Exception e){

        }
        return druidDataSource;
    }

    @Bean
    @Primary
    public DynamicDataSource dataSource() throws IOException {
        DynamicDataSource dynamicDataSource = new DynamicDataSource();
        dynamicDataSource.setDataSource(druidDataSource());
        dynamicDataSource.setTargetDataSources(new HashMap<>());
        return dynamicDataSource;
    }

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        this.applicationContext = applicationContext;
    }
}
